using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using PH.Mission;
using Hoshimi._Utilitaire_;


namespace Hoshimi._Map_._TSP_
{
	public class NavigationTSP : NavigationTSPBase<NavPointContainer>
	{
		#region Variables
		
		protected PathFinderConfig mPathFinderConfig;

		#endregion

		#region Getters & Setters

		public static MyMain myPlayer			{ get { return myMapManager.myPlayer ; } }
		public static MapManager myMapManager	{ get { return MapManager.getInstance(); } }
		public static PathManager myPathManager { get { return PathManager.getInstance(); } }

		#endregion

		#region Methods

		public List<NavPointContainer> FindBestPath(Point startLocation, List<NavPointContainer> navPointList, ref PathFinderConfig pathFinderConfig,int startTurn, int endTurn, ConstraintResolutionEnum resolutionType)
		{
			List<NavPointContainer> solution;

			try
			{
				solution = this.FindBestPathBis(startLocation, navPointList, ref pathFinderConfig, startTurn, endTurn, resolutionType);
			}
			#if DEBUG
            catch (Exception e)
            {
				this.PrintException(e);
                // Pour savoir quand ca crash...
                Debug.Assert(false, e.Message, e.StackTrace);

				return null;
            }
			#else
			catch (Exception e)
			{
				myPlayer.PrintException(e);

				return null;
			}
			#endif

			

			return solution;
		}

		protected List<NavPointContainer> FindBestPathBis(Point startLocation, List<NavPointContainer> navPointList, ref PathFinderConfig pathFinderConfig,int startTurn, int endTurn, ConstraintResolutionEnum resolutionType)
		{
			if (navPointList == null)
			{
				return null;
			}

			this.mPathFinderConfig = pathFinderConfig;

			List<TSPNodeBase<NavPointContainer>> nodeList = new List<TSPNodeBase<NavPointContainer>>(navPointList.Count);
			for(int i = 0; i < navPointList.Count; i++)
			{
				nodeList.Add(new TSPNode(navPointList[i]));
			}

			NavPoint startNavPoint	= new NavPoint();
			startNavPoint.Location	= startLocation;
			startNavPoint.StartTurn	= startTurn;
			startNavPoint.EndTurn	= startTurn;
			TSPNode startNode		= new TSPNode(new NavPointContainer(startNavPoint));

			nodeList = this.FindBestPath(startNode, nodeList, startTurn, endTurn, resolutionType);

			if (nodeList == null)
			{
				return null;
			}

			List<NavPointContainer> navPointListResult = new List<NavPointContainer>(nodeList.Count);
			List<Point> debugList = new List<Point>();
			foreach(TSPNode node in nodeList)
			{
				navPointListResult.Add(node.mNode);
				debugList.Add(node.mLocation);
			}

			return navPointListResult;
		}

		public override int GetTurnCost(Point startPoint, Point endPoint)
		{
			return myPathManager.GetTurnCost(startPoint, endPoint, ref this.mPathFinderConfig);
		}

		#endregion

		#region TSP Node definition
		
		protected class TSPNode : TSPNodeBase<NavPointContainer>
		{
			#region TSPNodeBase Members

			public override Point	mLocation	{ get { return this.mNode.Location; } }
			public override int		mStartTurn	{ get { return this.mNode.StartTurn; } }
			public override int		mEndTurn	{ get { return this.mNode.EndTurn; } }

			#endregion

			public TSPNode(NavPointContainer navPointContainer)
				: base(navPointContainer)
			{

			}
		}

		#endregion
		
	}
}
